package org.idontknow.blocks;

import org.apache.log4j.Logger;

abstract class Command {

	public static Logger log = Logger.getLogger(Command.class.getName());

	protected static Stack[] blockStack;

	protected Block blockFrom;

	protected Block blockTo;

	protected Stack stackFrom;

	protected Stack stackTo;

	public void execute() {
	}

	public static Block[] init(int size) {
		blockStack = new Stack[size];
		Block[] blocks = new Block[size];
		for (int i = 0; i < size; i++) {
			blockStack[i] = new Stack(size);
			blocks[i] = new Block(i, i, 0);
			blockStack[i].put(blocks[i]);
		}
		return blocks;
	}

	Command() {
	}

	Command(Block _from, Block _to) {
		blockFrom = _from;
		blockTo = _to;
		stackFrom = blockStack[blockFrom.getStackId()];
		// System.out.println("from stack: " + blockFrom.getStackId());
		stackTo = blockStack[blockTo.getStackId()];
	}

	public boolean isClean(int id, int pos) {
		return blockStack[id].isClean(pos);
	}

	public void returnStackAfter(int id, int pos) {
		int nbBlocksToReturn = blockStack[id].getNbBlocksUpon(pos);
		Block block;
		for (int i = 1; i <= nbBlocksToReturn; i++) {
			block = blockStack[id].pop();
			block.set(block.getValue(), 0);
			blockStack[block.getValue()].put(block);
		}
	}

	public void cleanFrom() {
		int stackId = blockFrom.getStackId();
		int posInStack = blockFrom.getPosInStack();
		if (!isClean(stackId, posInStack)) {
			returnStackAfter(stackId, posInStack);
		}
	}

	public void cleanTo() {
		int stackId = blockTo.getStackId();
		int posInStack = blockTo.getPosInStack();
		if (!isClean(stackId, posInStack)) {
			returnStackAfter(stackId, posInStack);
		}
	}

	public void moveBlocksOver(int from, int to, int nbBlockToMove) {
		if (nbBlockToMove == 1) {
			Block block = stackFrom.pop();
			block.set(to, stackTo.getNbBlocks());
			stackTo.put(block);
		} else {
			Stack temp = new Stack(nbBlockToMove);
			for (int i = 1; i <= nbBlockToMove; i++) {
				Block block = stackFrom.pop();
				block.set(-1, temp.getNbBlocks());
				temp.put(block);
			}
			for (int i = 1; i <= nbBlockToMove; i++) {
				Block block = temp.pop();
				block.set(to, stackTo.getNbBlocks());
				stackTo.put(block);
			}
		}
	}

	public static void printStacks() {
		System.out.println();
		for (int i = 0; i < blockStack.length; i++) {
			System.out.print("  " + i + " : ");
			blockStack[i].print();
			// System.out.print(" |-| " + blockStack[i].getNbBlocks());
			System.out.print("\n");
		}
		System.out.println();
	}
}
